#include "types.h"
#include "stdio.h"
#include "console.h"
#include "spinlock.h"

static struct spinlock printf_lock;

// 打印一个整数
static void printint(int xx, int base, int sign) {
    static char digits[] = "0123456789abcdef";
    char buf[16];
    int i;
    uint x;

    if (sign && (sign = xx < 0))
        x = -xx;
    else
        x = xx;

    i = 0;
    do {
        buf[i++] = digits[x % base];
    } while ((x /= base) != 0);

    if (sign)
        buf[i++] = '-';

    while (--i >= 0)
        console_putc(buf[i]);
}

// 打印一个指针
static void printptr(uint64 x) {
    int i;
    console_putc('0');
    console_putc('x');
    for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4)
        console_putc("0123456789abcdef"[x >> (sizeof(uint64) * 8 - 4)]);
}

// 格式化输出到控制台
int printf(const char *fmt, ...) {
    va_list ap;
    int i, c;
    char *s;

    acquire(&printf_lock);

    if (fmt == 0) {
        release(&printf_lock);
        return -1;
    }

    va_start(ap, fmt);
    for (i = 0; (c = fmt[i] & 0xff) != 0; i++) {
        if (c != '%') {
            console_putc(c);
            continue;
        }
        c = fmt[++i] & 0xff;
        if (c == 0)
            break;
        switch (c) {
        case 'c':
            console_putc(va_arg(ap, int));
            break;
        case 'd':
            printint(va_arg(ap, int), 10, 1);
            break;
        case 'x':
            printint(va_arg(ap, int), 16, 0);
            break;
        case 'p':
            printptr(va_arg(ap, uint64));
            break;
        case 's':
            if ((s = va_arg(ap, char *)) == 0)
                s = "(null)";
            for (; *s; s++)
                console_putc(*s);
            break;
        case '%':
            console_putc('%');
            break;
        default:
            // 打印未知格式
            console_putc('%');
            console_putc(c);
            console_puts("(E_FMT)");
            break;
        }
    }
    
    console_flush(); // 在printf结束时刷出所有剩余内容
    release(&printf_lock);
    return 0; // 简化返回值
}


